package card;

import utility.*;

/**
 * Class cardset contains list of card
 * 
 * 
 * @version 2.0.0
 */
public class Cardset {
	/**
	 * cards[] is the cards of a cardset max store the maximum size of a cardset
	 * n store the number of cards of a cardset
	 */
	protected Card[] cards;
	protected int max;
	protected int n;

	/**
	 * construct the class with a max number of cardset
	 * 
	 * @param max
	 */
	public Cardset(int max) {
		n = 0;
		this.max = max;
		cards = new Card[this.max];
	}

	/**
	 * copy constructor
	 * 
	 * @param c
	 */
	public Cardset(Cardset c) {
		n = 0;
		max = c.getMax();
		cards = new Card[c.getMax()];
		for (int i = 0; i < c.count(); i++)
			add(c.getCard(i));
	}

	/**
	 * Insert a Card object to the end of the Cardset.
	 * 
	 * @param c
	 *            The Card object to be inserted.
	 * @return A boolean value representing the success or failure of the
	 *         insertion.
	 */
	public boolean add(Card c) {
		try {
			cards[n++] = new Card(c);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * Insert a Cardset into the end of the existing Cardset.
	 * 
	 * @param cs
	 *            The Cardset object to be inserted.
	 * @return A boolean value representing the success or failure of the
	 *         insertion.
	 */
	public boolean add(Cardset cs) {
		int rem = max - n;
		if (cs.count() <= rem) {
			for (int i = 0; i < cs.count(); i++)
				add(cs.getCard(i));
			return true;
		} else
			return false;
	}

	/**
	 * Take out the Card object at the index i and remove it from the Cardset.
	 * 
	 * @param i
	 *            The index for the Card to be taken out.
	 * @return A Card object being taken out.
	 */
	public Card takeOut(int i) {
		try {
			if (n > 0) {
				Card temp;
				temp = cards[i];
				cards[i] = cards[n - 1];
				n--;
				return temp;
			} else
				return null;
		} catch (Exception e) {
			return null;
		}

	}

	/**
	 * Remove a Card from the Cardset which has the same value and suit as the
	 * Card object given by the parameter.
	 * 
	 * @param c
	 *            The Card object for comparison.
	 */
	public void remove(Card c) {
		int i = -1;
		boolean found = false;
		do {
			i++;
			found = cards[i].compare(c);
		} while (!found && i < count());

		if (found) {
			for (int j = i; j < count() - 1; j++)
				cards[j] = cards[j + 1];
			n--;
		}
	}

	/**
	 * Remove all the Card objects which have the same suit and value as the
	 * Card objects in the Cardset given in the parameter.
	 * 
	 * @param c
	 *            The Cardset object that is used for the comparison.
	 */
	public void remove(Cardset c) {

		for (int i = 0; i < c.count(); i++) {
			for (int j = 0; j < count(); j++)
				if (c.cards[i].compare(cards[j]))
					remove(cards[j]);
		}

	}

	/**
	 * Get the number of valid Card objects in the card set.
	 * 
	 * @return An integer representing the number of cards.
	 */
	public int count() {
		return n;
	}

	/**
	 * Get the maximum number of Card objects that this Cardset can hold.
	 * 
	 * @return An integer representing the max value.
	 */
	public int getMax() {
		return max;
	}

	/**
	 * Get the instance of a particular Card object.
	 * 
	 * @param i
	 *            Index for the Card.
	 * @return A card object.
	 *         <p>
	 *         (WARNING: This return an instance of the card object within the
	 *         class, it may be modified at any point.)
	 */
	public Card getCard(int i) {
		return new Card(cards[i]);
	}

	/**
	 * Clear all the existing Card objects in the Cardset.
	 */
	public void clear() {
		for (int i = 0; i < n; i++)
			cards[i].clear();
		n = 0;
	}

	/**
	 * Sort the cards array by value
	 */
	public void sort() {
		for (int i = 0; i < n; i++)
			for (int j = i; j > 0; j--)
				if (isALessThanB(cards[j], cards[j - 1]))
					swap(cards[j], cards[j - 1]);
	}

	/**
	 * Determine whether a is less than b
	 * 
	 * @param a
	 *            card a
	 * @param b
	 *            card b
	 * @return
	 */
	public boolean isALessThanB(Card a, Card b) {
		return cardHelper.value2priority(a.getValue()) < cardHelper
				.value2priority(b.getValue());
	}

	/**
	 * Do the swapping
	 * 
	 * @param c1
	 *            card 1
	 * @param c2
	 *            card 2
	 */
	public void swap(Card c1, Card c2) {
		char ts = c1.getSuit();
		char tv = c1.getValue();

		c1.setSuit(c2.getSuit());
		c1.setValue(c2.getValue());

		c2.setSuit(ts);
		c2.setValue(tv);
	}
}
